﻿using DotNetty.Common.Utilities;
using DotNetty.Transport.Channels;
using PSAMMatrixCloud.Common;
using PSAMMatrixCloud.Model;
using PSMMatrixCloud.Common;
using System;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace PSAMMatrixCloud.TransferSecret.LaneMutual
{
    public class LaneControler  
    {
        
        #region 解析设备端发送数据

        /// <summary>
        /// 解析返回数据
        /// </summary>
        /// <param name="clientIp"></param>
        /// <param name="clientPort"></param>
        /// <param name="msg"></param>
        /// <returns></returns>
        public Message AnalyseControlerData(IChannel channel, Message message)
        {
            Message responseMessage = null;
            switch ((DeviceCommandTypeAsk)message.CommandType)
            {
                case DeviceCommandTypeAsk.HeartBeat://心跳
                    responseMessage = AnalyseHeartBeat(channel, message);
                    break;
                case DeviceCommandTypeAsk.IdentityAuth://身份认证
                    responseMessage = AnalyseIdentityAuth(channel, message);
                    break;
                case DeviceCommandTypeAsk.VehicleInfo://车辆信息
                    responseMessage = AnalyseVehicleInfo(channel, message);
                    break;
                case DeviceCommandTypeAsk.MAC1://计算MAC1
                    responseMessage = AnalyseMac1(channel, message);
                    break;
                case DeviceCommandTypeAsk.MAC2://校验MAC2
                    responseMessage = AnalyseMac2(channel, message);
                    break;
                default:
                    break;
            }

            return responseMessage;
        }

        /// <summary>
        /// 解析心跳包数据
        /// </summary>
        private Message AnalyseHeartBeat(IChannel channel, Message data)
        {
            LogHelper.Info($"【心跳】 数据包内容：{ Common.JsonHelper.ToJsonByMillisecond(data)}");
            SessionInfo session = LaneChannelManager.GetSessionInfo(channel);//获取设备ID
            if ((session != null) || (!string.IsNullOrWhiteSpace(session.DeviceID)))
            {
                session.LastAccessTime = DateTime.Now;//设置最近访问时间
            }
            else
            {
                channel.CloseAsync();
                throw new Exception("设备还未接入,无法更新心跳在线信息");
            }
            byte[] id = new byte[4];
            Array.ConstrainedCopy(data.Body, 0, id, 0, 4);
            if (BitConverter.IsLittleEndian) // 若为 小端模式
            {
                Array.Reverse(id); // 转换为 大端模式               
            }
            int DeviceId = BitConverter.ToInt32(id, 0);

            Model.psam_deviceinfoModel deviceModel = new BLL.psam_deviceinfo().GetModel(DeviceId);
            if (deviceModel == null)
            {
                LogHelper.Error($"设备ID:{DeviceId.ToString()} 不存在");
                channel.CloseAsync();
                return null;
            }
            else
            {
                if (deviceModel.status == 0)
                {
                    channel.CloseAsync();
                    return null;
                }
            }
            LogHelper.Info($"设备ID:{DeviceId.ToString()} 心跳");
            //发送response
            Message msg = new Message((int)ServerCommandTypeReply.HeartBeat, (byte)((data.MessageID>>4) & (data.MessageID<<4)));
            Array.ConstrainedCopy(BitConverter.GetBytes(0), 0, msg.Body, 0, 1);
            Array.ConstrainedCopy(data.Body, 0, msg.Body, 1, 4);

            if (BitConverter.IsLittleEndian) // 若为 小端模式
            {
                byte[] dateBytes=BitConverter.GetBytes(DateTimeHelper.GetTimeStamp());
                Array.Reverse(dateBytes); // 转换为 大端模式     
                Array.ConstrainedCopy(dateBytes, 0, msg.Body, 5, 4);
            }
            else
            {
                Array.ConstrainedCopy(BitConverter.GetBytes(DateTimeHelper.GetTimeStamp()), 0, msg.Body, 5, 4);
            }
            return msg;
        }

        /// <summary>
        /// 解析身份认证数据
        /// </summary>
        private Message AnalyseIdentityAuth(IChannel channel, Message data)
        {
            LogHelper.Info($"【身份认证】 数据包内容：{ Common.JsonHelper.ToJsonByMillisecond(data)}");
            byte[] id = new byte[4];
            Array.ConstrainedCopy(data.Body, 0, id, 0, 4);
            if (BitConverter.IsLittleEndian) // 若为 小端模式
            {
                Array.Reverse(id); // 转换为 大端模式               
            }
            int DeviceId =BitConverter.ToInt32(id, 0);
            byte[] md5Bytes = new byte[16];
            Array.ConstrainedCopy(data.Body, data.Body.Length - 16, md5Bytes, 0, md5Bytes.Length);
            string md5 = BitConverter.ToString(md5Bytes).Replace("-", "").ToLower();//MD5

            bool flag = false;
            Model.psam_deviceinfoModel deviceModel = new BLL.psam_deviceinfo().GetModel(DeviceId);
            if (deviceModel == null)
            {
                LogHelper.Error($"解析身份认证数据,设备ID:{DeviceId.ToString()} 不存在");
                channel.CloseAsync();
                return null;
            }
            else
            {
                if(deviceModel.status==1)
                {
                    string unSign = DeviceId + deviceModel.signkey;

                    string sign = EncryptHelper.MD5Encrypt(32, unSign);//计算md5签名

                    if (string.Equals(md5, sign, StringComparison.CurrentCultureIgnoreCase))
                    {
                        flag = true;
                        LogHelper.Info($"设备ID:{DeviceId.ToString()} 身份认证成功");
                        //设置Channel会话信息
                        IAttribute<SessionInfo> attribute = channel.GetAttribute<SessionInfo>(LaneChannelManager.SESSION_KEY);
                        SessionInfo session = attribute.Get();
                        session.DeviceID = deviceModel.id.ToString();
                        session.DeviceKey = deviceModel.signkey;
                        //session.LastAccessTime = DateTime.Now;

                        LaneChannelManager.Add(DeviceId.ToString(), channel);//建立会话

                        
                    }
                    else
                    {
                        channel.CloseAsync();
                        return null;
                    }
                }
                else
                {
                    LogHelper.Info($"设备ID:{DeviceId.ToString()} 身份认证失败");
                    channel.CloseAsync();
                    return null;
                }
            }

            //发送response
            Message msg = new Message((int)ServerCommandTypeReply.IdentityAuth, (byte)((data.MessageID >> 4) & (data.MessageID << 4)));
            Array.ConstrainedCopy(data.Body, 0, msg.Body, 0, 4);
            Array.ConstrainedCopy(BitConverter.GetBytes(!flag), 0, msg.Body, 4, 1);
            return msg;
        }

        /// <summary>
        /// 解析车辆信息包数据
        /// </summary>
        private Message AnalyseVehicleInfo(IChannel channel, Message data) 
        {
            LogHelper.Info($"【解析车辆信息】 数据包内容：{ Common.JsonHelper.ToJsonByMillisecond(data)}");
            SessionInfo session = LaneChannelManager.GetSessionInfo(channel);//获取设备ID
            if ((session != null) || (!string.IsNullOrWhiteSpace(session.DeviceID)))
            {
                session.LastAccessTime = DateTime.Now;//设置最近访问时间
                session.CommandType = DeviceCommandTypeAsk.VehicleInfo;
            }
            else
            {
                channel.CloseAsync();
                throw new Exception("设备还未接入,无法解析车辆在线信息");
            }
            byte[] id = new byte[4];
            Array.ConstrainedCopy(data.Body, 0, id, 0, 4);
            if (BitConverter.IsLittleEndian) // 若为 小端模式
            {
                Array.Reverse(id); // 转换为 大端模式               
            }
            int DeviceId = BitConverter.ToInt32(id, 0);
            if (session.DeviceID!= DeviceId.ToString())
            {
                throw new Exception($"车辆数据包异常,设备id：{DeviceId}");
            }


            //将车辆信息发至PSAM加密盒子机解密
            string PSAMMatrixNo = PSAMMatrix.PSAMChannelManager.GetIdleMatrixNo();
           
            if (!string.IsNullOrWhiteSpace(PSAMMatrixNo))
            {
                LaneDataPackage laneDataPackage = new LaneDataPackage();
                laneDataPackage.PSAMMatrixNo = PSAMMatrixNo;
                laneDataPackage.PSAMNo = "FFFF";
                laneDataPackage.TerminalNo = "FFFFFFFFFFFF";
                laneDataPackage.DeviveID = session.DeviceID;
                laneDataPackage.CommandType = DeviceCommandTypeAsk.VehicleInfo;
                laneDataPackage.RecvTime = DateTime.Now;
                laneDataPackage.LaneData = data.ToBytes();

                PSAMMatrix.PSAMSocket.VehickeInfoEnqueue(PSAMMatrixNo, laneDataPackage);
                session.PSAMMatrixNo = PSAMMatrixNo;
                session.PSAMNo = laneDataPackage.PSAMNo;
                session.TerminalNo = laneDataPackage.TerminalNo;
                session.TransTime = DateTime.Now;
            }
            
            //发送response
            return null;
        }

        /// <summary>
        /// 解析MAC1包数据
        /// </summary>
        private Message AnalyseMac1(IChannel channel, Message data)
        {
            LogHelper.Info($"【计算MCA1】 数据包内容：{ Newtonsoft.Json.JsonConvert.SerializeObject(data)}");
            SessionInfo session = LaneChannelManager.GetSessionInfo(channel);//获取设备ID
            if ((session != null) || (!string.IsNullOrWhiteSpace(session.DeviceID)))
            {
                session.LastAccessTime = DateTime.Now;//设置最近访问时间
            }
            else
            {
                channel.CloseAsync();
                throw new Exception("设备还未接入,无法解析车辆在线信息");
            }
            byte[] id = new byte[4];

            Array.ConstrainedCopy(data.Body, 0, id, 0, 4);
            if (BitConverter.IsLittleEndian) // 若为 小端模式
            {
                Array.Reverse(id); // 转换为 大端模式               
            }
            int DeviceId = BitConverter.ToInt32(id);
            if (session.DeviceID != DeviceId.ToString())
            {
                channel.CloseAsync();
                throw new Exception($"mac1数据包异常,设备id：{DeviceId}");
            }

            //将mac1数据包发至PSAM加密盒子机计算mac1
            byte[] TerminalNo = new byte[6];
            Array.ConstrainedCopy(data.Body, 44, TerminalNo, 0, 6);
            if (session.TerminalNo == BitConverter.ToString(TerminalNo).Replace("-", ""))
            {
                LaneDataPackage laneDataPackage = new LaneDataPackage();
                laneDataPackage.PSAMMatrixNo = session.PSAMMatrixNo;
                laneDataPackage.PSAMNo = session.PSAMNo;
                laneDataPackage.TerminalNo = session.TerminalNo;
                laneDataPackage.DeviveID = session.DeviceID;
                laneDataPackage.CommandType = DeviceCommandTypeAsk.MAC1;
                laneDataPackage.RecvTime = DateTime.Now;
                laneDataPackage.LaneData = data.ToBytes();
                PSAMMatrix.PSAMSocket.MacInfoEnqueue(session.PSAMMatrixChannelNo, laneDataPackage);
            }

            session.TransTime = DateTime.Now;
            //发送response
            return null;
        }

        /// <summary>
        /// 解析MAC2包数据
        /// </summary>
        private Message AnalyseMac2(IChannel channel, Message data)
        {
            LogHelper.Info($"【验证MCA2】 数据包内容：{ Newtonsoft.Json.JsonConvert.SerializeObject(data)}");
            SessionInfo session = LaneChannelManager.GetSessionInfo(channel);//获取设备ID
            if ((session != null) || (!string.IsNullOrWhiteSpace(session.DeviceID)))
            {
                session.LastAccessTime = DateTime.Now;//设置最近访问时间
            }
            else
            {
                channel.CloseAsync();
                throw new Exception("设备还未接入,无法解析车辆在线信息");
            }

            byte[] id = new byte[4];

            Array.ConstrainedCopy(data.Body, 0, id, 0, 4);
            if (BitConverter.IsLittleEndian) // 若为 小端模式
            {
                Array.Reverse(id); // 转换为 大端模式               
            }
            int DeviceId = BitConverter.ToInt32(id);
            if (session.DeviceID != DeviceId.ToString())
            {
                channel.CloseAsync();
                throw new Exception($"mac2数据包异常,设备id：{DeviceId}");
            }
            //将车辆信息发至PSAM加密盒子机检验MAC2
            byte[] TerminalNo = new byte[6];
            Array.ConstrainedCopy(data.Body, 24, TerminalNo, 0, 6);
            if (session.TerminalNo == BitConverter.ToString(TerminalNo).Replace("-", ""))
            {
                LaneDataPackage laneDataPackage = new LaneDataPackage();
                laneDataPackage.PSAMMatrixNo = session.PSAMMatrixNo;
                laneDataPackage.PSAMNo = session.PSAMNo;
                laneDataPackage.TerminalNo = session.TerminalNo;
                laneDataPackage.DeviveID = session.DeviceID;
                laneDataPackage.CommandType = DeviceCommandTypeAsk.MAC2;
                laneDataPackage.RecvTime = DateTime.Now;
                laneDataPackage.LaneData = data.ToBytes();
                PSAMMatrix.PSAMSocket.MacInfoEnqueue(session.PSAMMatrixChannelNo, laneDataPackage);
            }

            session.TransTime = DateTime.Now;
            //发送response
            return null;
        }


        //发送数据
        private void SendData(string deviceID, Message message)
        {
            IChannel channel = LaneChannelManager.GetChannel(deviceID);

            if (channel != null)
            {
                channel.WriteAndFlushAsync(message);
                LogHelper.Info($"{deviceID} 下发 {message.CommandType} {message.MessageID}");
            }
            else
            {
                LogHelper.Error($"{deviceID} 未找到对应设备的连接,下发数据失败");
            }
        }
        #endregion
    }
}